using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;
using System.Web;
using Microsoft.SharePoint.WebPartPages;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Web.UI;
using System.Data;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Web.UI.HtmlControls;
using System.Collections;
using TST.SharePoint.Shared;

namespace TST.WebParts
{
    /// <summary>
    /// Field Editor for the Query Form webpart. Allows for easy editing of the fields. 
    /// Data will be loaded and saved from and to the webpart.
    /// </summary>
    /// <remarks>Used by the QueryFormFieldsEditor.aspx file. Place this file in the 
    /// C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS folder
    /// </remarks> 
    public class ContentByTypeEditor : UnsecuredLayoutsPageBase, ICallbackEventHandler
    {

        #region Private variables

        private const string DISPLAYDATAFORMATSTRING = "[{0}]";
        private SPSite _currentSite;
        private SPWeb _currentWeb;
        protected System.Web.UI.WebControls.Literal dialogDescription;
        protected System.Web.UI.WebControls.Literal dialogTitle;
        protected ContentTypeConfiguration contentTypeConfiguration;
        protected FieldsConfiguration fieldsConfiguration;
        protected Panel panelGrid;
        protected GridConfiguration gridConfiguration;
        protected Image pickerIcon;

        private string _selectedDatasource;
        private GridDatasource _datasource;

        protected GridDatasource Datasource
        {
            get
            {
                if (!string.IsNullOrEmpty(CurrentConfiguration.DatasourceID))
                {
                    if (_datasource == null)
                    {
                        _datasource = GridDatasource.GetDatasource(CurrentConfiguration);
                        _datasource.ReadConfiguration(CurrentConfiguration);
                        if (_datasource.GetType() == typeof(DatasourceContentType))
                        {
                            ((DatasourceContentType)_datasource).Web = _currentWeb;
                        }
                    }
                    return _datasource;
                }
                return null;
            }
        }

        private DatasourceConfiguration CurrentConfiguration
        {
            get
            {
                if (ViewState["CurrentConfiguration"]==null)
                {
                    ViewState["CurrentConfiguration"] = new DatasourceConfiguration();
                }
                return (DatasourceConfiguration)ViewState["CurrentConfiguration"];
            }
            set
            {
                ViewState["CurrentConfiguration"] = value;
            }

        }

        private DatasourceConfiguration EditConfiguration
        {
            get
            {
                if (ViewState["fieldsConfiguration"] == null)
                {
                    ViewState["fieldsConfiguration"] = new DatasourceConfiguration();
                }
                return (DatasourceConfiguration)ViewState["fieldsConfiguration"];
            }
            set
            {
                ViewState["fieldsConfiguration"] = value;
            }

        }

        public SPLimitedWebPartManager WebPartManager
        {
            get
            {
                SPLimitedWebPartManager webPartManager = null;

                if (_currentWeb != null)
                {
                    webPartManager = _currentWeb.GetLimitedWebPartManager(PageUrl, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
                    return webPartManager;
                }
                return null;
            }
        }

        private Exception _exception = null;
        #endregion

        #region Constant Values
        private const string ContentByTypeHelpKey = "ContentByTypeEditorHelp";
        #endregion

        #region Properties

        ///// <summary>
        ///// Gets or sets the page Url.
        ///// </summary>
        ///// <value>The page Url.</value>
        private string PageUrl
        {
            get { return (string)(ViewState["pageUrl"] ?? string.Empty); }
            set { ViewState["pageUrl"] = value; }
        }

        ///// <summary>
        ///// Gets or sets the site Url.
        ///// </summary>
        ///// <value>The site Url.</value>
        private string SiteUrl
        {
            get { return (string)(ViewState["siteUrl"] ?? string.Empty); }
            set { ViewState["siteUrl"] = value; }
        }

        private SPSite CurrentSite
        {
            get
            {
                if (_currentSite == null)
                {
                    _currentSite = new SPSite(this.SiteUrl);
                }
                return _currentSite;
            }
        }

        private SPWeb CurrentWeb
        {
            get
            {
                if (_currentWeb == null)
                {
                    _currentWeb = CurrentSite.OpenWeb();
                }
                return _currentWeb;
            }
        }

        /// <summary>
        /// Gets or sets the relative resource path.
        /// </summary>
        /// <value>The relative resource path.</value>
        private string RelativeResourcePath
        {
            get { return (string)(ViewState["relativeResourcePath"] ?? string.Empty); }
            set { ViewState["relativeResourcePath"] = value; }
        }

        /// <summary>
        /// Gets or sets the list control options cache.
        /// </summary>
        /// <value>The list control options cache.</value>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        private object listControlOptionsCache
        {
            get
            {
                return ViewState["listControlOptionsCache"];
            }
            set
            {
                ViewState["listControlOptionsCache"] = value;
            }
        }

        /// <summary>
        /// Gets or sets the Unique ID (storage key) of the web part.
        /// </summary>
        /// <value>The storage key.</value>
        private string StorageKey
        {
            get { return ((string)ViewState["storageKey"] ?? string.Empty); }
            set { ViewState["storageKey"] = value; }
        }

        private void InitSPWeb()
        {
            if (Request.QueryString["storageKey"] != null)
                this.StorageKey = Request.QueryString["storageKey"];

            if (Request.QueryString["pageUrl"] != null)
                this.PageUrl = HttpUtility.UrlDecode(Request.QueryString["pageUrl"]);

            if (Request.QueryString["siteUrl"] != null)
                this.SiteUrl = HttpUtility.UrlDecode(Request.QueryString["siteUrl"]);

            if (SiteUrl == string.Empty)
            {
                _currentWeb = SPContext.Current.Web;
            }
            else
            {
                _currentSite = new SPSite(SiteUrl);
                _currentWeb = _currentSite.OpenWeb();
            }
            contentTypeConfiguration.Web = _currentWeb;
            fieldsConfiguration.Web = _currentWeb;
            gridConfiguration.Web = _currentWeb;
        }

        private void DisposeSPWeb()
        {
            if (_currentWeb != null)
                _currentWeb.Dispose();
            if (_currentSite != null)
                _currentSite.Dispose();
        }

        #endregion

        #region Events


        /// <summary>
        /// Raises the <see cref="E:Init"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            try
            {
                base.OnInit(e);
                InitSPWeb();
                // Event handlers
                contentTypeConfiguration.SelectedContentTypeChanged += new EventHandler(contentTypeConfiguration_SelectedContentTypeChanged);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(string.Format("OnInit: {0} - {1}", ex.Message, ex.InnerException));
                throw;
            }
        }

        private void contentTypeConfiguration_SelectedContentTypeChanged(object sender, EventArgs e)
        {
            if (this.Page.IsPostBack)
            {
                CurrentConfiguration.Fields.Clear();
                if (fieldsConfiguration != null)
                    fieldsConfiguration.Clear();
                if (gridConfiguration != null)
                    gridConfiguration.Clear();
            }
        }


        protected void ButtonOK_Click(object sender, EventArgs e)
        {
            if (this.Page.IsValid)
            {
                if (SaveData())
                {
                    string script = "ConfigurationSaved();";
                    ClientScriptManager cm = Page.ClientScript;
                    this.Page.ClientScript.RegisterStartupScript(typeof(ContentByTypeEditor), "CloseCBTEditForm", script, true);
                }
            }
        }

        protected override void OnUnload(EventArgs e)
        {
            base.OnUnload(e);
            DisposeSPWeb();
        }

        /// <summary>
        /// Raises the <see cref="E:Load"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            try
            {
                ((DialogMaster)base.Master).OkButton.Click += new EventHandler(this.ButtonOK_Click);
                ((DialogMaster)base.Master).HelpKey = ContentByTypeHelpKey;

                ClientScriptManager cm = Page.ClientScript;
                String cbReference = cm.GetCallbackEventReference(this, "arg", "ReceiveServerData", "");
                String callbackScript = String.Format(CultureInfo.CurrentCulture, "function CallServerToSave(arg, context) {{ {0}; }}", cbReference);
                cm.RegisterClientScriptBlock(this.GetType(), "CallServerToSave", callbackScript, true);

                if (base.IsPostBack)
                {
                    if (!SPUtility.ValidateFormDigest())
                    {
                        //throw new SPException(Resources.GetString("ErrorSecurityValidationFailed"));
                    }
                    SetConfigurationControl();
                }
                else
                {
                    this.ConfigureDialog();
                    this.RetrieveConfiguration();
                }

                base.OnLoad(e);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(string.Format("Onload: {0} - {1}", ex.Message, ex.InnerException));
                throw;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            SetConfigurationControl();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            try
            {
                base.Render(writer);

                if (_exception!=null)
                    writer.Write(string.Format("Error getting webpart: {0}", _exception.Message));
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(string.Format("Render: {0} - {1}", ex.Message, ex.InnerException));
                throw;
            }
        }

        /// <summary>
        /// Configures the dialog.
        /// </summary>
        private void ConfigureDialog()
        {
            try
            {
                dialogTitle.Text = "Content By Type configuration editor";
                pickerIcon.ImageUrl = "/_layouts/images/actionssettings.gif";
                dialogDescription.Text = "Use this editor to configure your Content By Type WebPart. Configure the datasource, select and configure the fields you want the webpart to display and configure the display options.";
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(string.Format("ConfigureDialog: {0} - {1}", ex.Message, ex.InnerException));
                throw;
            }
        }

        /// <summary>
        /// Saves the data.
        /// </summary>
        /// <returns></returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private bool SaveData()
        {
            try
            {
                SetConfigurationControl();
                WriteConfiguration();

                SPLimitedWebPartManager manager = this.WebPartManager;
                System.Web.UI.WebControls.WebParts.WebPart webPart = manager.WebParts[this.StorageKey];

                ContentByTypeWebPart cbt = (ContentByTypeWebPart)webPart;

                cbt.Configuration = CurrentConfiguration.WriteXml();
                manager.SaveChanges(webPart);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        #endregion


        #region Save Xml Data

        private void ReadConfiguration()
        {
            if (CurrentConfiguration == null)
            {
                return;
            }
            contentTypeConfiguration.ReadConfiguration();
            fieldsConfiguration.ReadConfiguration();
            gridConfiguration.ReadConfiguration();
        }

        private void WriteConfiguration()
        {
            contentTypeConfiguration.WriteConfiguration();
            fieldsConfiguration.WriteConfiguration(false);
            gridConfiguration.WriteConfiguration();
        }

        private void SetConfigurationControl()
        {
            contentTypeConfiguration.CurrentConfiguration = CurrentConfiguration;
            contentTypeConfiguration.Datasource = Datasource;
            fieldsConfiguration.CurrentConfiguration = CurrentConfiguration;
            fieldsConfiguration.EditConfiguration = EditConfiguration;
            fieldsConfiguration.Datasource = Datasource;
            gridConfiguration.CurrentConfiguration = CurrentConfiguration;
            gridConfiguration.EditConfiguration = EditConfiguration;
            gridConfiguration.Datasource = Datasource;
        }

        #endregion

        #region Load and Parse Xml Data

        /// <summary>
        /// Retrieves the field definitions.
        /// </summary>
        private void RetrieveConfiguration()
        {
            try
            {
                SPLimitedWebPartManager manager = this.WebPartManager;
                System.Web.UI.WebControls.WebParts.WebPart webPart = manager.WebParts[this.StorageKey];

                ContentByTypeWebPart cbt = (ContentByTypeWebPart)webPart;

                if (cbt.Configuration == string.Empty)
                    CurrentConfiguration = new DatasourceConfiguration();
                else
                    CurrentConfiguration = DatasourceConfiguration.ReadXml(cbt.Configuration);
                SetConfigurationControl();

                _selectedDatasource = cbt.DataSources[0].Id;
                SetSelectedDatasource();
                ReadConfiguration();

            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(string.Format("RetrieveConfiguration: {0}", ex.ToString()));
                throw;
            }

        }

        private void SetSelectedDatasource()
        {
            CurrentConfiguration.DatasourceID = _selectedDatasource;
        }

        #endregion

        #region ICallbackEventHandler Members

        private string returnValueCallBack;

        /// <summary>
        /// Returns the results of a callback event that targets a control.
        /// </summary>
        /// <returns>The result of the callback.</returns>
        public string GetCallbackResult()
        {
            return returnValueCallBack;
        }

        /// <summary>
        /// Processes a callback event that targets a control.
        /// </summary>
        /// <param name="eventArgument">A string that represents an event argument to pass to the event handler.</param>
        public void RaiseCallbackEvent(string eventArgument)
        {
            returnValueCallBack = string.Empty;
        }

        #endregion
    }
}
